﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Threading;
using AzureDiagMon.Common.Helpers;
using AzureDiagMon.Common.Mvvm.Interfaces;
using Ninject;
using Ninject.Parameters;

namespace AzureDiagMon.Common.Mvvm.Helpers
{
    public static class ViewModelHelper
    {
        [Inject]
        private static IScreenDefinitionFactory screenDefinitionFactory;

        public static ViewModel GetViewModel(string viewName)
        {
            var nameVariants = new List<string>(new[] { viewName });

            if (viewName.EndsWith(NamingConvention.ViewModelSuffix))
            {
                //Remove the ViewModel suffix 
                var str = viewName.Substring(0, Math.Max(0, viewName.Length -
                    NamingConvention.ViewModelSuffix.Length));

                if (!String.IsNullOrEmpty(str))
                    nameVariants.Add(str);
            }
            else
            {
                nameVariants.Add(String.Concat(viewName, NamingConvention.ViewModelSuffix));
            }

            //TODO: Implement locator
            var result = IoC.Get<IViewModel>((IEnumerable<string>)nameVariants) as ViewModel;

            return result;
        }

        public static object GetView(IChildViewModel viewModel)
        {
            var attr = viewModel.GetType().GetCustomAttributes(typeof(ViewModelAttribute), false)
                            .FirstOrDefault() as ViewModelAttribute;

            //TODO: More smart solution needed
            if (attr == null)
                return null;

            return IoC.Get<object>(String.Format("View:{0}", attr.ViewName));
        }

        public static ScreenDefintion[] GetScreens()
        {
            //var result = Bootstrapper.Container.GetExports<IViewModel, IScreenViewModelMetadata>()
            //                                   .Where(e => e.Metadata.IsScreen)
            //                                   .OrderBy(e => e.Metadata.ViewName)
            //                                   .OrderBy(e => e.Metadata.Order)
            //                                   .Select(e => screenDefinitionFactory.CreateScreenDefintion(e.Metadata.ViewName))
            //                                   .ToArray();
            ScreenDefintion[] result = new ScreenDefintion[0];
            return result;
        }
    }

    public interface IScreenDefinitionFactory
    {
        ScreenDefintion CreateScreenDefintion(string screenName);
    }

    public abstract class ScreenDefinitionFactory : IScreenDefinitionFactory
    {
        public abstract ScreenDefintion CreateScreenDefintion(string screenName);
    }

    public class ScreenDefintion : IScreenDefintion
    {
        public Type ScreenType { get; set; }
        public Type ViewModelType { get; set; }

        private object view;
        public object View
        {
            get
            {
                if (view == null)
                    view = Activator.CreateInstance(ScreenType);

                return view;
            }
        }

        public ScreenDefintion(Type screenType, Type viewModelType)
        {
            ScreenType = screenType;
            ViewModelType = viewModelType;
        }
    }

    public interface IScreenDefintion
    {
        Type ScreenType { get; set; }
        Type ViewModelType { get; set; }
        object View { get; }
    }

}
